/** Copyright (c) 2020 by XMX
 *	file : tyger.h
 *	since : 2020-08-22
 *	server : Tyger 0.0.1
 */

/* $begin tyger.h */
//#ifndef __TYGER_H__
//#define __TYGER_H__

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<fcntl.h>
#include<unistd.h>
#include<signal.h>
#include<netdb.h>
#include<sys/stat.h>
#include<sys/socket.h>
#include<sys/wait.h>
#include<sys/mman.h>
//#include<arpa/inet.h>

// $begin---------------structs, variables, and constants-------------------

/* Persistent state for robust I/O (Rio) package */
/* $begin rio_t */
#define RIO_BUFSIZE 8192
typedef struct {
	int rio_fd;
	int rio_cnt;
	char *rio_bufptr;
	char rio_buf[RIO_BUFSIZE];
}rio_t;
/* $end rio_t */

typedef struct sockaddr SA;

/* External variables */
extern char **environ;	/* defined by libc */

/* Misc constants */
#define MAXLINE 8192	/* Max text line length */
#define MAXBUF 8192	/* Max I/O buffer size */
#define LISTENQ 1024 /* Second argument to listen() */

// $end---------------structs, variables, and constants---------------------

// $begin-------------------------functions---------------------------------

/* Error-handling functions */
void unix_error(char *msg);

/* Process control wrappers */
pid_t Fork(void);
void Execve(const char *filename, char *const argv[], char *const envp[]);
pid_t Wait(int *status);
pid_t Waitpid(pid_t pid, int *status, int options);

/* Singal wrappers */
typedef void handler_t (int);
handler_t *Signal(int sig, handler_t *handler);
void SigHandler(int sig);

/* Unix I/O wrappers */
int Open(const char *pathname, int flags, mode_t mode);
ssize_t Read(int fd, void *buf, size_t count);
ssize_t Write(int fd, const void *buf, size_t count);
void Close(int fd);
int Dup2(int fd1, int fd2);
void Stat(const char *filename, struct stat *statbuf);
void Fstat(int fd, struct stat *statbuf);

/* Memory mapping wrappers */
void *Mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
void Munmap(void *start, size_t length);

/* Sockets interface wrappers */
int Socket(int domain, int type, int protocol);
void Setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
void Bind(int sockfd, struct sockaddr *addr, socklen_t addrlen);
void Listen(int sockfd, int backlog);
int Accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
void Connect(int sockfd, struct sockaddr *serv_addr, socklen_t addrlen);

/* Protocol independent wrappers */
void Getaddrinfo(const char *host, const char *service, const struct addrinfo *hints, struct addrinfo **result);
void Getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *host, size_t hostlen, char *service, size_t servlen, int flags);
void Freeaddrinfo(struct addrinfo *result);

/* Rio (Robust I/O) package */
ssize_t rio_readn(int fd, void *usrbuf, size_t n);
ssize_t rio_writen(int fd, void *usrbuf, size_t n);
void rio_readinitb(rio_t *rp, int fd);
ssize_t rio_readbnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);

/* Wrappers for Rio package */
ssize_t Rio_readn(int fd, void *usrbuf, size_t n);
void Rio_writen(int fd, void *usrbuf, size_t n);
void Rio_readinitb(rio_t *rp, int fd);
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n);
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);

/* 	This funciton is reentrant and protocol-independent. */
int open_listenfd (char *port);

/* Wrappers for reentrant protocol -independent heplers */
int Open_listenfd (char *prot);

/* business logic function defined in util.c */
void doit(int fd);
void read_requesthdrs(rio_t *rp);
int parse_uri(char *uri, char *filename, char *cgiargs);
void serve_static(int fd, char *filename, int filesize);
void get_filetype(char *filename, char *filetype);
void serve_dynamic(int fd, char *filename, char *cgiargs);
void clienterror(int fd, char *cause, char *errnum, char *shortmsg, char *longmsg);

// $end---------------------------functions---------------------------------

//#endif
/* $end tyger.h */
